package logger

import (
	"fmt"
	"io"
	"os"
	"path"
	"strings"
	"time"

	"gitee.com/xxhsjp/x-core/model"
	"gitee.com/xxhsjp/x-core/utils/xfiles"
	"gitee.com/xxhsjp/x-core/utils/xstrings"

	"runtime"

	nested "github.com/antonfisher/nested-logrus-formatter"
	rotatelogs "github.com/lestrrat/go-file-rotatelogs"

	// "github.com/rifflock/lfshook"
	"gitee.com/xxhsjp/x-core/conf"
	"github.com/sirupsen/logrus"
)

var config = &model.LogConfig{File: "logs/web.log", Stdout: true, Level: "info", RotationHours: 24, RotationCount: 5}

func init() {
	bindDefaultConfig()

	logFileString := config.File
	if !xstrings.IsBlank(logFileString) {
		dir := path.Dir(logFileString)
		if !xfiles.ExistDir(dir) {
			os.MkdirAll(dir, os.ModePerm)
		}
	}

	logger := &loggerParam{
		logFile:       logFileString,
		rotationTime:  time.Duration(config.RotationHours),
		rotationCount: config.RotationCount,
	}

	fileCutlogger := fileCutLogger(logger)

	logrus.SetFormatter(formatter())
	logrus.SetReportCaller(true)
	var writers []io.Writer
	if config.Stdout {
		writers = append(writers, os.Stdout)
	}
	writers = append(writers, fileCutlogger)

	logrus.SetOutput(io.MultiWriter(writers...))

	var l logrus.Level
	switch config.Level {
	case "error":
		l = logrus.ErrorLevel
	case "debug":
		l = logrus.DebugLevel
	case "warn":
		l = logrus.WarnLevel
	default:
		l = logrus.InfoLevel
	}
	logrus.SetLevel(l)
}

func bindDefaultConfig() {
	viper := conf.Wrapper
	viper.UnmarshalKey("log", config)
	logrus.Debugf("log config: %+v", config)
}

func fileCutLogger(param *loggerParam) *rotatelogs.RotateLogs {
	os.MkdirAll(path.Dir(param.logFile), 0755)
	logFile := strings.TrimSuffix(param.logFile, ".log") + ".%Y%m%d.log"
	logier, err := rotatelogs.New(
		// 切割后日志文件名称
		logFile,
		// rotatelogs.WithLinkName(Current.LogDir),   // 生成软链，指向最新日志文件
		// rotatelogs.WithMaxAge(30*24*time.Hour),    // 文件最大保存时间
		rotatelogs.WithRotationTime(param.rotationTime*time.Hour), // 日志切割时间间隔
		rotatelogs.WithRotationCount(param.rotationCount),
	)

	if err != nil {
		panic(err)
	}
	// lfHook := lfshook.NewHook(lfshook.WriterMap{
	// 	logrus.InfoLevel:  logier,
	// 	logrus.FatalLevel: logier,
	// 	logrus.DebugLevel: logier,
	// 	logrus.WarnLevel:  logier,
	// 	logrus.ErrorLevel: logier,
	// 	logrus.PanicLevel: logier,
	// },
	// 	// 设置分割日志样式
	// 	formatter())
	// logrus.AddHook(lfHook)
	return logier
}

func formatter() *nested.Formatter {

	return &nested.Formatter{
		HideKeys:        true,
		NoColors:        true,
		TimestampFormat: "2006-01-02 15:04:05.000",
		FieldsOrder:     []string{"serialNo", "user", "ip", "url", "status", "latency", "reqBody", "respBody"},
		CustomCallerFormatter: func(c *runtime.Frame) string {
			name := c.File[strings.LastIndex(c.File, "/")+1:]

			return fmt.Sprintf(" (%s:%d %s)", name, c.Line, c.Function)
		},
	}
}

type loggerParam struct {
	logFile string
	// maxAge        time.Duration
	rotationTime  time.Duration
	rotationCount int
}
